/*
 * Project 2 - Process Scheduler
 * Team - BitwiseGuys
 * Team members: Tyson Lewis, Josh Warner, Dallas Rosson, Ken Norton
 */

package backend;

import java.util.ArrayDeque;
import java.util.List;
import java.util.Queue;

import backend.SchedulerProcess.ProcessType;

/**
 * @author Ken Norton
 */
public class Scheduler {
	
	private static final PCB IDLE_PROCESS = new PCB(-1, new SchedulerProcess(ProcessType.IDLE, 100000, null, null));
	
	/**
	 * The ready queue. This holds the processes waiting to be run.
	 */
	private Queue<PCB> my_ready_queue;
	
	/**
	 * The number of steps that the scheduler will run on the CPU
	 */
	private int my_steps;
	
	/**
	 * The processes currently in memory.
	 */
	private SchedulerProcess my_processes[];
	
	/**
	 * The pcbs for the processes.
	 */
	private PCB my_pcbs[];
	
	/**
	 * The default constructor.
	 */
	public Scheduler(final List<String> the_list) {
		my_steps = 0;
		
		Loader loader = new Loader(the_list);
		
		my_processes = loader.getProcessArray();
		
		my_pcbs = loader.getPCBArray();
		
		my_ready_queue = new ArrayDeque<>();
		
		for (int i = 0; i < my_pcbs.length; i++) {
			my_ready_queue.add(my_pcbs[i]);
		}
	}
	
	/**
	 * Places the process passes in in the ready queue, and gets the 
	 * next process.
	 * 
	 * @param the_proc
	 * @return
	 */
	public PCB schedule(final PCB the_proc) {
		//PCB next = my_ready_queue.poll();
		if (the_proc != null) {
			//my_ready_queue.add(the_proc);
			//System.out.println("add to red q");
			addToReadyQ(the_proc);
		}
		PCB next = my_ready_queue.poll();
		return next;
	}
	
	/* ************************************************
	 * Setters
	 **************************************************/
	void addToReadyQ(PCB the_pcb){
		my_ready_queue.add(the_pcb);
	}
	
	
	/* ************************************************
	 * Getters
	 **************************************************/
	
	/**
	 * Gets the next process from the ready queue or returns the
	 * IDLE_PROCESS if the queue is empty.
	 * 
	 * @return
	 */
	PCB getNextProcess(){
		if (my_ready_queue.size() == 0) {
			return IDLE_PROCESS;
		} 
		
		return my_ready_queue.poll();
	}
	
	/**
	 * Gets the number of steps that the scheduler will run.
	 * 
	 * @return The number of steps that the scheduler will run.
	 */
	public int getSteps() {
		return my_steps;
	}
	
	/**
	 * Gets a string that represents the processes in the ready queue.
	 * 
	 * @return A String representation of the ready queue.
	 */
	public String getReadyQueue() {
		StringBuffer sb = new StringBuffer();
		String output = "";
		for(PCB pcb: my_ready_queue){
			sb.append(pcb.getPid() + ", ");
		}
		sb.append(IDLE_PROCESS.getPid());
		if (sb.length() > 2){
			output = sb.substring(0, sb.length() - 2);
		}
		
		return output;
	}
}
